package org.hjl.commonutils.excel;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;

/**
 * excel导出工具类
 *
 * @author hjl
 * @version 1.0
 * @since 2024-08-06 14:14
 */
public class ExcelUtil {

    /**
     * 简单导出excel表格
     *
     * @param excelName  excel名称
     * @param sheetName  数据表名称
     * @param clazz      模型类型
     * @param recordList 导出集合
     */
    public static <T> void exportExcel(String excelName, String sheetName, Class<T> clazz, Collection<T> recordList) throws IOException {
        HttpServletResponse resp = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        try {
            if (null == resp) {
                throw new RuntimeException("无法以文件流形式进行返回！" );
            }
            setExcelResponseProp(resp, excelName);
            // 获取响应流
            EasyExcel.write(resp.getOutputStream())
                    .head(clazz)
                    .excelType(ExcelTypeEnum.XLSX)
                    .sheet(sheetName)
                    // 读取数据列表
                    .doWrite(Arrays.asList(recordList.toArray()));
        } catch (IOException e) {
            throw new IOException();
        }

    }

    /**
     * 设置响应结果
     *
     * @param response    响应结果对象
     * @param rawFileName 文件名
     * @throws UnsupportedEncodingException 不支持编码异常
     */
    private static void setExcelResponseProp(HttpServletResponse response, String rawFileName) throws UnsupportedEncodingException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" );
        response.setCharacterEncoding("utf-8" );
        String fileName = URLEncoder.encode(rawFileName, StandardCharsets.UTF_8).replaceAll("/" , "%20" );
        response.setHeader("Content-disposition" , "attachment;filename*=utf-8''" + fileName + ".xlsx" );
    }

    /**
     * 以模板新式导出
     *
     * @param fileName   resource/templates文件夹下指定模板名称
     * @param recordList 数据列表
     * @param response   响应体
     */
    public static void exportTemplate(String fileName, Collection<T> recordList, HttpServletResponse response) throws IOException {
        //设置响应头内容，以vnd.ms-excel方式打开数据
        response.setContentType("application/vnd.ms-excel" );
        //修改响应头信息
        response.setHeader("Content-disposition" , String.format("attachment; filename=\"%s\"" , fileName + ".xlsx" ));
        //告诉所有浏览器不要缓存
        response.setHeader("Cache-Control" , "no-cache" );
        response.setHeader("Pragma" , "no-cache" );
        //设置时间值属性的响应头信息，不要缓存
        response.setDateHeader("Expires" , -1);
        //(设置输出的编码格式)指定输出到客户端的时候，这些文字使用UTF-8编码
        response.setCharacterEncoding("UTF-8" );
        // 获取resource/templates文件夹下指定模板
        ClassLoader classLoader = ExcelUtil.class.getClassLoader();
        InputStream inputStream = classLoader.getResourceAsStream("templates/" + fileName);
        //使用模版创建工作簿
        try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), T.class).withTemplate(inputStream).excelType(ExcelTypeEnum.XLS).build()) {
            WriteSheet sheet = EasyExcel.writerSheet().build();
            //开启自动换行,自动换行表示每次写入一条list数据是都会重新生成一行空行,此选项默认是关闭的,需要提前设置为true
            // FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
            //多行数据填充
            excelWriter.write(recordList, sheet);
            //关闭流
            excelWriter.finish();
        } catch (IOException e) {
            throw new IOException();
        }
    }


}
